package sistemadeproyectos;

import javax.swing.DefaultListModel;
import java.net.*;
import java.io.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;

public class RepositorioCliente extends javax.swing.JFrame {

    /* Socket que se conecta al servidor de Repositorio*/
    private Socket conexion;

    /** Entrada de datos asociado al socket**/
    private ObjectInputStream entrada;

    /** Salida de datos asociado al socket**/
    private ObjectOutputStream salida;

    /* Identificador del usuario que esta conectado*/
    private Usuario usuarioActivo;
    
    /* Identificador del Equipo al cual esta conectado el usuario*/
    private Equipo equipoActual;
    
    private DefaultListModel modelo = new DefaultListModel();
 
    private String barra(){
        String resultado = "";
        if(System.getProperty("os.name").substring(0,5).equals("Windo")){
            resultado = "\\";
        }
        else if(System.getProperty("os.name").substring(0,5).equals("Linux")){
            resultado = "/";
        }
        return resultado;
    }
    
    /** Creates new form RepositorioCliente */
    public RepositorioCliente(Equipo elEquipo, Usuario elUsuario) 
            throws Exception {
        initComponents();
        ServersConf rutas = new ServersConf();
        try {
            this.equipoActual = elEquipo;
            this.usuarioActivo = elUsuario;
            (this.conexion) = new Socket (rutas.getIPRepositorio(), rutas.getPuertoRepositorio()); /**Aca se establece conexion con el servidor. */
            (this.entrada) = new ObjectInputStream ((this.conexion).getInputStream());
            (this.salida) = new ObjectOutputStream ((this.conexion).getOutputStream());
            jLabel1.setText("Repositorio del Equipo " + (this.equipoActual).getIdEquipo());
            jList1.setModel(modelo); 
            
            /* Se escribe el nombre del usuario y del equipo
             * al que esta asociado el usuario conectado*/
            (this.salida).writeObject((this.usuarioActivo).getUsuario());
            (this.salida).writeObject((this.equipoActual).getIdEquipo());
            
            //Se listan los archivos
            listar_archivos();    
        } 
        catch (Exception e) {
            limpiar_socket();
            throw e;
        }        
    }

    public void setUsuario(Usuario elUsuario){
        this.usuarioActivo = elUsuario;
    }
    
    public void setEquipo(Equipo elEquipo){
        this.equipoActual = elEquipo;
    }
    
    private void listar_archivos() throws IOException, ClassNotFoundException {
          /**Se lee la lista de archivos de la carpeta del equipo*/
          ArrayList<String> archivos = (ArrayList<String>)(this.entrada).readObject();
        
          Iterator<String> it = archivos.iterator();
          /* Si se intento acceder al directorio anterior al del equipo
           * No se hace nada*/    
          if (it.hasNext()) {
              String primer_elem = it.next();
              if (!(primer_elem.equals("/denegado/"))) {
                  (this.modelo).clear();            
                  (this.modelo).addElement(primer_elem);             
                  while (it.hasNext()) {
                    (this.modelo).addElement(it.next());
                  }
              }
          }    
          else { (this.modelo).clear(); }
    }
    
    /**
     * Cierra el socket; asi como la salida y entrada de datos del mismo.
     */
    private void limpiar_socket() {
        try { 
          (this.entrada).close();
          (this.salida).close();
          (this.conexion).close();
        } catch (Exception e) {}
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();
        jLabel1 = new javax.swing.JLabel();
        jAbrir = new javax.swing.JButton();
        jRetroceder = new javax.swing.JButton();
        jDescargar = new javax.swing.JButton();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();
        jButton4 = new javax.swing.JButton();
        Historial_button = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Repositorio");
        setResizable(false);
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        jScrollPane1.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Lista de Archivos:", javax.swing.border.TitledBorder.LEFT, javax.swing.border.TitledBorder.ABOVE_TOP, new java.awt.Font("Times New Roman", 1, 18))); // NOI18N

        jList1.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jList1.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                jList1ValueChanged(evt);
            }
        });
        jScrollPane1.setViewportView(jList1);

        jLabel1.setFont(new java.awt.Font("Times New Roman", 1, 18));
        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel1.setText("Titulo");

        jAbrir.setText("Abrir Carpeta");
        jAbrir.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jAbrirActionPerformed(evt);
            }
        });

        jRetroceder.setText("Retroceder Directorio");
        jRetroceder.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRetrocederActionPerformed(evt);
            }
        });

        jDescargar.setText("Descargar Archivo");
        jDescargar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jDescargarActionPerformed(evt);
            }
        });

        jButton1.setText("Cargar Archivo");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jButton2.setText("Eliminar Archivo");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                EliminarArchivoActionPerformed(evt);
            }
        });

        jButton3.setText("Crear Carpeta");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                crearArchivoActionPerformed(evt);
            }
        });

        jButton4.setText("Salir");
        jButton4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                salirActionPerformed(evt);
            }
        });

        Historial_button.setText("Ver Historial");
        Historial_button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Historial_buttonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 511, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 339, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(Historial_button, javax.swing.GroupLayout.DEFAULT_SIZE, 166, Short.MAX_VALUE)
                            .addComponent(jButton4, javax.swing.GroupLayout.DEFAULT_SIZE, 166, Short.MAX_VALUE)
                            .addComponent(jDescargar, javax.swing.GroupLayout.DEFAULT_SIZE, 166, Short.MAX_VALUE)
                            .addComponent(jRetroceder, javax.swing.GroupLayout.DEFAULT_SIZE, 166, Short.MAX_VALUE)
                            .addComponent(jAbrir, javax.swing.GroupLayout.DEFAULT_SIZE, 166, Short.MAX_VALUE)
                            .addComponent(jButton1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 166, Short.MAX_VALUE)
                            .addComponent(jButton2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 166, Short.MAX_VALUE)
                            .addComponent(jButton3, javax.swing.GroupLayout.DEFAULT_SIZE, 166, Short.MAX_VALUE))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(27, 27, 27)
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 373, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(52, 52, 52)
                        .addComponent(jAbrir)
                        .addGap(18, 18, 18)
                        .addComponent(jRetroceder)
                        .addGap(18, 18, 18)
                        .addComponent(jDescargar)
                        .addGap(18, 18, 18)
                        .addComponent(jButton1)
                        .addGap(18, 18, 18)
                        .addComponent(jButton2)
                        .addGap(18, 18, 18)
                        .addComponent(jButton3)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 14, Short.MAX_VALUE)
                        .addComponent(Historial_button)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jButton4)))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jAbrirActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jAbrirActionPerformed
        // TODO add your handling code here:
        try {
            int index = jList1.getSelectedIndex();
            if (index >= 0) {
                String carpeta = (String)(this.modelo).get(index);
                if (carpeta.endsWith(barra())) {
                    //quitamos el ultimo slash
                    int lim = carpeta.lastIndexOf(barra());
                    carpeta = carpeta.substring(0, lim);
                    (this.salida).writeObject("abrir");
                    (this.salida).writeObject(carpeta);
                    listar_archivos();
                }
            }
        } catch (Exception e) { 
            JOptionPane.showMessageDialog(this, "Error al establecer conexion con servidor.", 
                "Error en Conexion", JOptionPane.ERROR_MESSAGE);
            limpiar_socket();
            this.dispose(); 
          }        
    }//GEN-LAST:event_jAbrirActionPerformed

    private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_jList1ValueChanged
        // TODO add your handling code here:
        int index = jList1.getSelectedIndex();
        if ((index >= 0) && (index < (jList1.getModel()).getSize())) {
            String carpeta = (String)(this.modelo).get(index);       
            if (carpeta.endsWith(barra())) { 
                jAbrir.setEnabled(true); 
                jDescargar.setEnabled(false);
            }
            else { 
                jAbrir.setEnabled(false);
                jDescargar.setEnabled(true);
            }
        }
    }//GEN-LAST:event_jList1ValueChanged

    private void jRetrocederActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRetrocederActionPerformed
        // TODO add your handling code here:
        try {
            (this.salida).writeObject("atras");
            listar_archivos();
        } catch (Exception e) { 
            JOptionPane.showMessageDialog(this, "Error al establecer conexion con servidor.", 
                "Error en Conexion", JOptionPane.ERROR_MESSAGE);
            limpiar_socket();
            this.dispose(); 
          }
    }//GEN-LAST:event_jRetrocederActionPerformed

    private void jDescargarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jDescargarActionPerformed
        // TODO add your handling code here:
        int index = jList1.getSelectedIndex();
        FileOutputStream fileout_archivo = null;
        try {
            if (index >= 0) {
                String nom_arch = (String)(this.modelo).get(index);

                /**Creamos el archivo de flujo de salida de la cancion*/
                JFileChooser fileChooser = new JFileChooser();   
                fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                int result = fileChooser.showOpenDialog(null);
                if (result == JFileChooser.APPROVE_OPTION ){
                    String loc_arch = (fileChooser.getSelectedFile()).getPath() + "/" + nom_arch;

                    /**Le pedimos al servidor el archivo a descargar*/
                    (this.salida).writeObject("descargar");
                    (this.salida).writeObject(nom_arch);

                    /**Leemos el arreglo de bytes del servidor*/ 
                    byte[] bytes_archivo = (byte[])(this.entrada).readObject();

                    /**Copiamos la respuesta del servidor (los bytes) al archivo*/
                    fileout_archivo = new FileOutputStream(loc_arch); 
                    /**Creamos un apuntador a ese archivo para escribir los bytes*/
                    BufferedOutputStream buffout = new BufferedOutputStream(fileout_archivo);
                    /** Escribimos los bytes de la cancion que mando el servidor
                     * en el filedescriptor
                     */
                    buffout.write(bytes_archivo);
                    /**Obligamos a que escriba en disco duro*/
                    buffout.flush();
                
                    fileout_archivo.close();                
                    buffout.close();
                    
                    JOptionPane.showMessageDialog(this, "Se ha descargado el archivo con exito.", 
                        "Archivo Descargado", JOptionPane.INFORMATION_MESSAGE);
                }
            }
        }
        catch (Exception e) {
            JOptionPane.showMessageDialog(this, "Error al descargar el archivo.", 
                "Error en Conexion", JOptionPane.ERROR_MESSAGE);
            // OJO NO SE ESTAN BORRANDO LOS REMANENTES DEL ARCHIVO DESCARGADO
            // DEL DISCO SI ES QUE LA DESCARGA FUE LA QUE SE CORROMPIO
            if (fileout_archivo != null) { 
                try { fileout_archivo.close(); } catch (IOException e2) {}
            }
            limpiar_socket();
            this.dispose(); 
        }
    }//GEN-LAST:event_jDescargarActionPerformed

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
    try{    
        JFileChooser fileChooser = new JFileChooser();   
        fileChooser.setAcceptAllFileFilterUsed(false);
        int result = fileChooser.showOpenDialog(null);
        if (result == JFileChooser.APPROVE_OPTION ){
            String ruta_arch = fileChooser.getSelectedFile().getPath();
            String nombre_arch = fileChooser.getSelectedFile().getName();
            (this.salida).writeObject("cargar");
            (this.salida).writeObject(nombre_arch); 
            FileInputStream arch = new FileInputStream(ruta_arch);  
            byte[] arr = new byte[arch.available()];
            arch.read(arr);
            (this.salida).writeObject(arr);
            listar_archivos();
        }
    }
    catch (Exception e){}
}//GEN-LAST:event_jButton1ActionPerformed

private void EliminarArchivoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_EliminarArchivoActionPerformed
    try{
    (this.salida).writeObject("eliminar");
    int index = jList1.getSelectedIndex();
    String nom_arch = (String)(this.modelo).get(index);
    (this.salida).writeObject(nom_arch);
    listar_archivos();
    }
    catch (Exception e){}
}//GEN-LAST:event_EliminarArchivoActionPerformed

private void crearArchivoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_crearArchivoActionPerformed
   try{ 
   (this.salida).writeObject("carpeta");
   String seleccion = JOptionPane.showInputDialog(
        this, "Introduzca el nombre de la carpeta", //Mensaje
        "Nombre de carpeta: ", 
        JOptionPane.QUESTION_MESSAGE);
   (this.salida).writeObject(seleccion);
   listar_archivos();
   }
   catch(Exception e){}
}//GEN-LAST:event_crearArchivoActionPerformed

private void salirActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_salirActionPerformed
   try{ 
        (this.salida).writeObject("salir");
        this.dispose();
   }
   catch(Exception e){}
}//GEN-LAST:event_salirActionPerformed

private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
    // TODO add your handling code here:
    try{
        (this.salida).writeObject("salir");
    }
    catch(IOException ioe){}
    limpiar_socket();
}//GEN-LAST:event_formWindowClosing

    private void Historial_buttonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Historial_buttonActionPerformed
        try {
            Historial_Repositorio VentanaHist = new Historial_Repositorio(this,
                    true, (this.equipoActual));
            VentanaHist.setVisible(true);       
        }
        catch (SQLException e1) {             
                JOptionPane.showMessageDialog(this, "Error al construir el historial: " 
                +e1.getMessage(), "Error en Conexion", JOptionPane.ERROR_MESSAGE);
        }        
    }//GEN-LAST:event_Historial_buttonActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(RepositorioCliente.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(RepositorioCliente.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(RepositorioCliente.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(RepositorioCliente.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton Historial_button;
    private javax.swing.JButton jAbrir;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JButton jButton4;
    private javax.swing.JButton jDescargar;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JList jList1;
    private javax.swing.JButton jRetroceder;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration//GEN-END:variables
}